Using a movie data export component to create a QuickTime movie file is similar in many respects to creating an AIFF file, as shown in the previous example. Media data is handled differently in each case, however.
Listing 8 illustrates the first step, instantiating the movie data export component for video data.
Listing 8 Instantiating a movie data export component
ComponentDescription cd;
MovieExportComponent ci;
cd.componentType = MovieExportType;
cd.componentSubType = `MooV';
cd.componentManufacturer = `appl';
cd.componentFlags = canMovieExportFromProcedures;
cd.componentFlagsMask = canMovieExportFromProcedures;
ci = OpenComponent(FindNextComponent(nil, &cd));
Listing 9 illustrates the next step: configuring the data export component to create a single output video track. The call to MovieExportAddDataSource provides the callback functions for supplying media data.
Listing 9 Configuring the movie data export component
#define kMySampleRate 2997 // 29.97 fps
#define kMyFrameDuration 100 // one frame at 29.97 fps
typedef struct
{
GWorldPtr gw; // Temporary GWorld we use during export
ImageDescriptionHandle imageDescription;
long trackID;
}
MyReferenceRecord;
MyReferenceRecord myRef;
myRef.gw = nil;
myRef.imageDescription = nil;
MovieExportAddDataSource(ci, VideoMediaType, kMySampleRate,
&myRef.trackID, getVideoPropertyProc,
getVideoDataProc, &myRef);
The foregoing process should be repeated for as many video and sound sources as will be exported. However, it's important to realize that not all exporters supporting export from procedures can export an arbitrary number of sources. For the case where an exporter supports fewer sources than the application needs to export, the application must precomposite the video sources or mix the sound sources before providing them to the exporter.
Listing 10 Exporting video data
StandardFileReply reply;
Handle dataRef;
// get output file from user
QTNewAlias(&reply.sfFile, (AliasHandle *)&dataRef, true);
MovieExportFromProceduresToDataRef(ci, dataRef, rAliasType);
The getVideoPropertyProc function returns information about the output track's properties (for example, the compression format). If the function doesn't return a value for a particular property, the exporter will choose a default value based (usually) on the source data format. In Listing 11 , dimensions are set to 160x120 and the compression format is set to JPEG. All other properties are unspecified.
Listing 11 Obtaining information about output track properties
pascal OSErr getVideoPropertyProc(void *refcon, long trackID,
OSType propertyType, void *propertyValue)
{
OSErr err = noErr;
switch (propertyType) {
case meWidth:
*(Fixed *)propertyValue = 160L << 16;
break;
case meHeight:
*(Fixed *)propertyValue = 120L << 16;
break;
case scSpatialSettingsType:
{
SCSpatialSettings *ss = propertyValue;
ss->codecType = kJPEGCodecType;
ss->codec = 0;
ss->depth = 0;
ss->spatialQuality = codecNormalQuality;
}
break;
default:
err = paramErr;
break;
}
return err;
}
The videoGetDataProc function provides video frames to the export operation. In the example in Listing 12 , the same blank frame is returned for each request. The export operation ends when this function returns eofErr . Any data allocated by videoGetDataProc must be disposed of after the export operation is complete.
Listing 12 Providing video frames for export
pascal OSErr getVideoDataProc(void *refCon,
MovieExportGetDataParams *params)
{
OSErr err = noErr;
MyReferenceRecord *myRef = (MyReferenceRecord *)refCon;
TimeRecord tr;
if (params->requestedTime > kMySampleRate * 10)
return eofErr;// end of data after 10 seconds
if (!myRef->gw) {
Rect r;
CGrafPtr savePort;
GDHandle saveGD;
SetRect(&r, 0, 0, 320, 240);
NewGWorld(&myRef->gw, 32, &r, nil, nil, 0);
LockPixels(myRef ->gw->portPixMap);
MakeImageDescriptionForPixMap(myRef->gw->portPixMap,
&myRef->imageDescription);
GetGWorld(&savePort, &saveGD);
SetGWorld(myRef->gw, nil);
EraseRect(&r);
SetGWorld(savePort, saveGD);
}
params->dataPtr = GetPixBaseAddr(myRef->gw->portPixMap);
params->dataSize = (**myRef->imageDescription).dataSize;
params->actualTime = params->requestedTime;
params->descType = VideoMediaType;
params->descSeed = 1;
params->desc = (SampleDescriptionHandle)
myRef->imageDescription;
params->durationPerSample = kMyFrameDuration;
params->sampleFlags = 0;
}
The number and kind of data sources supported varies from one exporter to another. In the foregoing examples, AIFF only supports sound data sources while the QuickTime movie exporter accepts both sound and video data sources. Furthermore, an exporter may require at least one data source of some type. In others, it may accept 0 to some maximum number of data sources of a particular type.
Because the kinds and number of data sources supported varies from exporter to exporter, and may change with new versions of a particular exporter, there needs to be a way for a client of an exporter to determine this information. In QuickTime 4, a procedure-supporting exporter has a new kind of public component resource that provides this information. For a detailed description, see "Movie Export Component Resources" .
| Previous | Chapter Contents | Chapter Top | Next |